Ext.define('planner.view.Jobs.JobsGraph', {
	extend: 'Ext.view.AbstractView', 
	alias : 'widget.JobsGraph',
	title: 'JobsGraph',
	itemSelector: 'div.thumb-wrap',
	html: '<div id="graphContainer" style="overflow:hidden;width:100%;background:url(\'mxgraph/examples/editors/images/grid.gif\');height:100%;cursor:default;"></div>',
	requires: [
		'planner.store.Jobs',
	],
	listeners: {
		beforeitemclick: function(view, record, item) {
			console.log('beforeitemclick ' + item.dom);
		},
		render: function(v) {
			var me = this;
			//me.main(document.getElementById('graphContainer'));
			v.dragZone = Ext.create('Ext.dd.DragZone', v.getEl(), {
				getDragData: function(e) {
					var sourceEl = e.getTarget(v.itemSelector, 10), d;
					if (sourceEl) {
						console.log(sourceEl + ', data=' + v.getRecord(sourceEl).data.name);
						d = sourceEl.cloneNode(true);
						d.id = Ext.id();
						return v.dragData = {
							sourceEl: sourceEl,
							repairXY: Ext.fly(sourceEl).getXY(),
							ddel: d,
							blockData: v.getRecord(sourceEl)
						};
					}
				},
				getRepairXY: function() {
					return this.dragData.repairXY;
				}
			});
			v.dragZone.addToGroup('g1');

			this.dropZone = new Ext.dd.DropZone(this.getEl(), {
				getTargetFromEvent: function(e) {
					return e.getTarget('.thumb-wrap');
				},
				onNodeDrop : function(target, dd, e, data) {
					var r = me.getRecord(target);
					console.log('CommonDiagramm onNodeDrop type=' + data.blockData.get('name') + ', ' + target + ', ' + r.get('name'));
        			if(data.blockData.self.getName() == 'planner.model.Jobs')
						me.fireEvent('linkJobToParent', me, r, data.blockData);
        			else if(data.blockData.self.getName() == 'planner.model.Users')
						me.fireEvent('linkDeveloperToJob', me, data.blockData, r);

					
					return true;
				}
			});
		}
	},
	// Defines a new class for all icons
	mxIconSet: function (me, state) {
		this.images = [];
		var graph = state.view.graph;
		var md = (mxClient.IS_TOUCH) ? 'touchstart' : 'mousedown';
		
		/*// Icon1
		var img = mxUtils.createImage('mxgraph/examples/images/copy.png');
		img.setAttribute('title', 'Duplicate');
		img.style.position = 'absolute';
		img.style.cursor = 'pointer';
		img.style.width = '16px';
		img.style.height = '16px';
		img.style.left = (state.x + state.width) + 'px';
		img.style.top = (state.y + state.height) + 'px';
		
		mxEvent.addListener(img, md, mxUtils.bind(this, function(evt) {
				var s = graph.gridSize;
				graph.setSelectionCells(graph.moveCells([state.cell], s, s, true));
				mxEvent.consume(evt);
				this.destroy();
			})
		);
		
		state.view.graph.container.appendChild(img);
		this.images.push(img);*/
		
		// Delete
		var img = mxUtils.createImage('mxgraph/examples/images/delete2.png');
		img.setAttribute('title', 'Delete');
		img.style.position = 'absolute';
		img.style.cursor = 'pointer';
		img.style.width = '16px';
		img.style.height = '16px';
		img.style.left = (state.x + state.width) + 'px';
		img.style.top = (state.y - 16) + 'px';
		
		mxEvent.addListener(img, md, mxUtils.bind(this, function(evt) {
				// Disables dragging the image
				mxEvent.consume(evt);
			})
		);
		
		mxEvent.addListener(img, 'click', mxUtils.bind(this, function(evt) {
				me.fireEvent('removeJobEvent', state.cell.record);
				graph.removeCells([state.cell]);
				mxEvent.consume(evt);
				this.destroy();
			})
		);
		
		state.view.graph.container.appendChild(img);
		this.images.push(img);
	},
	addElement: function (store, records) {
		// Gets the default parent for inserting new cells. This
		// is normally the first child of the root (ie. layer 0).
		var graph = this.graph;
		var parent = graph.getDefaultParent();

		var xmlDocument = mxUtils.createXmlDocument();
		//var sourceNode = xmlDocument.createElement('Source');
		//var targetNode = xmlDocument.createElement('Target');

						
		// Adds cells to the model in a single step
		graph.getModel().beginUpdate();
		try
		{
			var elements = Array();
			for(i=0; i < records.length; i++) {
				var record = records[i];
				console.log(record.get('name'));
				//elements[record.get('id')] = graph.insertVertex(parent, null, record.get('name'), 90*i, 50*i, 80, 30);
				elements[record.get('id')] = graph.insertVertex(parent, null, xmlDocument.createElement(record.get('name')), 90*i, 50*i, 80, 30);
				elements[record.get('id')].record = record;
			}
			//var v2 = graph.insertVertex(parent, null, 'World!', 200, 150, 80, 30);
			for(i=0; i < records.length; i++) {
				console.log('asd');
				var record = records[i];
				if(record.get('parent') >= 0)
					var e1 = graph.insertEdge(parent, null, '', elements[record.get('id')], elements[record.get('parent')]);
			}
		}
		finally
		{
			// Updates the display
			graph.getModel().endUpdate();
		}
	},

	initComponent: function(arguments) {
		var me = this;

		var userTpl = new Ext.XTemplate(
		    '<tpl for=".">',
		        '<div style="margin-bottom: 10px;" class="thumb-wrap">',
		          '<h1>{name}</h1>',
		          '<img src="images/job.png" />',
		          '<br/><span>{id}({parent})-{name}</span>',
		          	'<div>Developers: ',
			    		'<tpl for="developers">',
			    			'<span>{name},</span>',
			    		'</tpl>',
		    		'</div>',
		        '</div>',
		    '</tpl>'
		);
		me.tpl = userTpl;
		// Defines an icon for creating new connections in the connection handler.
		// This will automatically disable the highlighting of the source vertex.
		mxConnectionHandler.prototype.connectImage = new mxImage('mxgraph/examples/images/connector.gif', 16, 16);
		// Enables crisp rendering of rectangles in SVG
		mxRectangleShape.prototype.crisp = true;

		me.mxIconSet.prototype.destroy = function() {
			if (this.images != null) {
				for (var i = 0; i < this.images.length; i++) {
					var img = this.images[i];
					img.parentNode.removeChild(img);
				}
			}
			
			this.images = null;
		};

		// Program starts here. Creates a sample graph in the
		// DOM node with the specified ID. This function is invoked
		// from the onLoad event handler of the document (see below).
		me.main = function(container) {
			// Checks if the browser is supported
			if (!mxClient.isBrowserSupported()) {
				// Displays an error message if the browser is not supported.
				mxUtils.error('Browser is not supported!', 200, false);
			} else {
				// Creates the graph inside the given container
				var graph = new mxGraph(container);
				me.graph = graph;
				graph.setConnectable(true);
				
				// Defines the tolerance before removing the icons
				var iconTolerance = 40;

				// Overrides method to store a cell label in the model
				var cellLabelChanged = graph.cellLabelChanged;
				graph.cellLabelChanged = function(cell, newValue, autoSize)
				{					
					cellLabelChanged.apply(this, arguments);
					me.fireEvent('updateJobEvent', cell.record, newValue);
				};
				
				// Removes cells when [DELETE] is pressed
				var keyHandler = new mxKeyHandler(graph);
				keyHandler.bindKey(46, function(evt)
				{
					if (graph.isEnabled())
					{
						//console.log(evt)
						graph.removeCells();
					}
				});

				graph.getModel().addListener(mxEvent.CHANGE, function(sender, event) {
					console.log('event: ' + mxEvent.CHANGE)
					graph.validateGraph();
				});

				var addEdgeHandler = graph.addEdge;
				graph.addEdge = function(edge, parent, source, target, index)
				{
					console.log('addEdge')
					addEdgeHandler.apply(this, arguments);
					if(target && source)
						me.fireEvent('linkJobToParent', me, target.record, source.record)
					//return addEdgeHandler(edge, parent, source, target, index);
				};

				// Shows icons if the mouse is over a cell
				graph.addMouseListener( {
				    currentState: null,
				    currentIconSet: null,
				   	mouseDown: function(sender, me) {
				    	// Hides icons on mouse down
			        	if (this.currentState != null) {
			          		this.dragLeave(me.getEvent(), this.currentState);
			          		this.currentState = null;
			        	}
				    },
				    mouseMove: function(sender, me) {
				    	if (this.currentState != null && (me.getState() == this.currentState || me.getState() == null)) {
				    		var tol = iconTolerance;
				    		var tmp = new mxRectangle(me.getGraphX() - tol, me.getGraphY() - tol, 2 * tol, 2 * tol);

				    		if (mxUtils.intersects(tmp, this.currentState)) {
				    			return;
				    		}
				    	}
				    	
						var tmp = graph.view.getState(me.getCell());
				    	
				    	// Ignores everything but vertices
						if (graph.isMouseDown || (tmp != null && !graph.getModel().isVertex(tmp.cell))) {
							tmp = null;
						}

				      	if (tmp != this.currentState) {
				        	if (this.currentState != null)
				        	{
				          		this.dragLeave(me.getEvent(), this.currentState);
				        	}
				        
			        		this.currentState = tmp;
				        
				        	if (this.currentState != null)
				        	{
				          		this.dragEnter(me.getEvent(), this.currentState);
				        	}
				      	}
				    },
				    mouseUp: function(sender, me) { },
				    dragEnter: function(evt, state)
				    {
				    	if (this.currentIconSet == null)
				    	{
			    			this.currentIconSet = new me.mxIconSet(me, state);
				    	}
				    },
				    dragLeave: function(evt, state)
				    {
				    	if (this.currentIconSet != null)
				    	{
			    			this.currentIconSet.destroy();
			    			this.currentIconSet = null;
				    	}
				    }
				});
				graph.setMultigraph(false);
				graph.setTooltips(true);
				// Source nodes needs 1..2 connected Targets
				graph.multiplicities.push(new mxMultiplicity(
				   true, null, null, null, 0, 1, null,
				   'Source Must Have 1 or 2 Targets',
				   'Source Must Connect to Target'));
				/*graph.multiplicities.push(new mxMultiplicity(
				   false, null, null, null, 0, null, null,
				   'Source Must Have 1 or 2 Targets',
				   'Source Must Connect to Target'));*/

				// Enables rubberband selection
				new mxRubberband(graph);
			}
		};
		me.store = Ext.create('planner.store.Jobs');
		//me.bindStore(me.store);
		me.store.on({
			'load': function (store, records) {
				console.log(records);
				me.main(document.getElementById('graphContainer'));
				me.addElement(store, records);
			},
			'add': function(store, records) {
				me.addElement(store, records);
			},
			'remove': function () {
				//alert(1);
			},

		});
		this.callParent(arguments);
	}
}); 
